package com.bkgy.util.createUtil;

import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 修改表名、生成模块名、模块描述
 * 运行后在当前项目下生成对应的模块
 * 【风险提示】：生成时会删除模块名位置的同名文件，生成的模块如果加了新功能或发生修改，重新生成会删除同名文件
 *
 * @author lixm
 * @Date 2025-09-08
 */
public class CreateUtil {
    //=============================================================
    private static String tableName = "REP_TCM_OUTPUT_INF";          //表名
    private static String modelName = "abcd";                   //生成模块名
    private static String description = "酸轧报表总览";     //模块说明
    private static boolean withCRUD = false;                     //是否包含增删改查
    // ============================================================

    static String pubPath = null;

    public static void main(String[] args) throws Exception {
        String schema = "BIGDATA";
        String modelPath = "com.bkgy.controller";//本溪项目模块结构

        //初始化源码位置
        pubPath = new File(CreateUtil.class.getResource("/").getFile()).getParentFile().getParentFile().getPath() + "\\src\\main";
        //创建目录
        StringBuffer sbf = new StringBuffer();
        String[] arr = modelPath.split("\\.", -1);
        for (int i = 0; i < arr.length; i++) {
            sbf.append("\\\\").append(arr[i]);
        }
        String path = sbf.toString();
        createDir(path);
        System.out.println("目录创建完毕");

        Connection conn = getConnection();
        Statement stmt = conn.createStatement();
        String sql = "SET CURRENT SCHEMA " + schema;
        stmt.execute(sql);

        //表列名
        List<TableObj> columnList = getAllColumn(conn, schema, tableName);
        close(null, stmt, conn);

        Set<String> importList = new HashSet<>();
        List<String> fieldList = new ArrayList<>();
        for (TableObj obj : columnList) {
            if (obj.getColumnName().matches(".*\\d.*")) {
                fieldList.add("@TableField(\"" + obj.getColumnName() + "\")");
                importList.add("import com.baomidou.mybatisplus.annotation.TableField;");
            }
            String comment = StringUtils.isNotEmpty(obj.getColumnComment()) ? "//" + obj.getColumnComment() : "";
            if ("VARCHAR".equals(obj.getTypeName())) {
                fieldList.add("private String " + convertToCamelCaseManual(obj.getColumnName()) + ";" + comment);
            } else if ("DECIMAL".equals(obj.getTypeName())) {
                fieldList.add("private BigDecimal " + convertToCamelCaseManual(obj.getColumnName()) + ";" + comment);
                importList.add("import java.math.BigDecimal;");
            } else if ("INTEGER".equals(obj.getTypeName())) {
                fieldList.add("private Integer " + convertToCamelCaseManual(obj.getColumnName()) + ";" + comment);
            } else if ("TIMESTAMP".equals(obj.getTypeName())) {
                fieldList.add("private Date " + convertToCamelCaseManual(obj.getColumnName()) + ";" + comment);
                importList.add("import java.util.Date;");
            } else {
                System.err.println("未处理的列类型" + obj.getTypeName() + ",列名：" + obj.getColumnName());
                fieldList.add("private String " + convertToCamelCaseManual(obj.getColumnName()) + ";" + comment);
            }
        }

        String className = firstChar2Up(convertToCamelCaseManual(tableName));
        //生成类文件
        createEntity(path, modelPath, className, importList, fieldList);

        //生成Mapper文件
        createMapper(path, modelPath, className);

        //生成service接口
        createService(path, modelPath, className);

        //生成service实现类
        createServiceImpl(path, modelPath, className);

        //生成controller文件
        createController(path, modelPath, className);

        //生成xml文件
        createXml(modelPath, className);
        System.out.println("模块生成完毕");
    }

    private static Connection getConnection() {
        String url = "jdbc:db2://10.171.7.100:50000/appdb";
        String driverName = "com.ibm.db2.jcc.DB2Driver";
        String username = "dsc";
        String pwd = "dscdsc1";

        Connection con = null;
        try {
            Class.forName(driverName);
            con = DriverManager.getConnection(url, username, pwd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return con;
    }

    private static void close(ResultSet rs, Statement stmt, Connection con) {
        try {
            if (rs != null) rs.close();
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        try {
            if (stmt != null) stmt.close();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
        try {
            if (con != null) con.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static List<TableObj> getAllColumn(Connection conn, String schema, String tableName) throws SQLException {
        List<TableObj> columnList = new ArrayList<TableObj>();
        //区分大小写
        ResultSet rs = conn.getMetaData().getColumns(null, schema, tableName, "%");
        while (rs.next()) {
            TableObj obj = new TableObj();
            obj.setColumnName(rs.getString("COLUMN_NAME"));
            obj.setDataType(rs.getInt("DATA_TYPE"));
            obj.setTypeName(rs.getString("TYPE_NAME"));
            obj.setColumnSize(rs.getInt("COLUMN_SIZE"));
            obj.setColumnComment(rs.getString("REMARKS"));
            columnList.add(obj);
        }
        return columnList;
    }

    //创建模块目录
    private static void createDir(String path) {
        File javaParent = new File(pubPath, "java" + path);
        File xmlParent = new File(pubPath, "resources/mybatis");
        if (!javaParent.exists()) {
            javaParent.mkdirs();
            System.out.println("创建目录：" + javaParent.getAbsolutePath());
        }
        File modelPath = new File(javaParent, modelName);
        if (!modelPath.exists()) {
            modelPath.mkdir();
            System.out.println("创建：" + modelPath.getAbsolutePath());
        }
        File f1 = new File(modelPath, "controller");
        if (!f1.exists()) {
            f1.mkdir();
            System.out.println("创建：" + f1.getAbsolutePath());
        }
        File f2 = new File(modelPath, "service");
        if (!f2.exists()) {
            f2.mkdir();
            System.out.println("创建：" + f2.getAbsolutePath());
        }
        File f22 = new File(f2, "impl");
        if (!f22.exists()) {
            f22.mkdir();
            System.out.println("创建：" + f22.getAbsolutePath());
        }

        File f3 = new File(modelPath, "entity");
        if (!f3.exists()) {
            f3.mkdir();
            System.out.println("创建：" + f3.getAbsolutePath());
        }

        if (withCRUD) {
            File f33 = new File(modelPath, "entity/pdo");
            if (!f33.exists()) {
                f33.mkdir();
                System.out.println("创建：" + f33.getAbsolutePath());
            }
        }

        File f4 = new File(modelPath, "mapper");
        if (!f4.exists()) {
            f4.mkdir();
            System.out.println("创建：" + f4.getAbsolutePath());
        }
        if (!xmlParent.exists()) {
            xmlParent.mkdirs();
            System.out.println("创建目录：" + xmlParent.getAbsolutePath());
        }
        File f5 = new File(xmlParent, modelName);
        if (!f5.exists()) {
            f5.mkdir();
            System.out.println("创建：" + f5.getAbsolutePath());
        }
    }

    private static String convertToCamelCaseManual(String upperCaseString) {
        upperCaseString = upperCaseString.toLowerCase();
        String[] parts = upperCaseString.split("_");
        StringBuilder sbf = new StringBuilder();
        for (int i = 0; i < parts.length; i++) {
            if (i > 0) {
                sbf.append(Character.toUpperCase(parts[i].charAt(0)));
                sbf.append(parts[i].substring(1));
            } else {
                sbf.append(parts[i]);
            }
        }
        return sbf.toString();
    }

    private static String firstChar2Up(String str) {
        if (str == null || str.length() == 0) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    //创建XML文件
    private static void createXml(String modelPath, String className) throws Exception {
        File entityPath = new File(pubPath + "/resources/mybatis/" + modelName, className + "Mapper.xml");
        if (entityPath.exists()) {
            entityPath.delete();
        }
        FileOutputStream fos = new FileOutputStream(entityPath);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        bw.write("<!DOCTYPE mapper\n");
        bw.write("        PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n");
        bw.write("        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n");
        bw.write("<mapper namespace=\"" + modelPath + "." + modelName + ".mapper.I" + className + "Mapper\">\n\n");
        bw.write("</mapper>\n");

        bw.close();

        System.out.println("XML文件创建完毕");
    }

    //创建服务实现类
    private static void createServiceImpl(String path, String modelPath, String className) throws IOException {
        File entityPath = new File(pubPath + "/java/" + path + "/" + modelName + "/service/impl", className + "ServiceImpl.java");
        if (entityPath.exists()) {
            entityPath.delete();
        }
        FileOutputStream fos = new FileOutputStream(entityPath);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write("package " + modelPath + "." + modelName + ".service.impl;\n\n");
        bw.write("import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;\n");
        bw.write("import " + modelPath + "." + modelName + ".entity." + className + ";\n");
        if (withCRUD) {
            bw.write("import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\n");
            bw.write("import com.baomidou.mybatisplus.core.metadata.IPage;\n");
            bw.write("import com.baomidou.mybatisplus.extension.plugins.pagination.Page;\n");
            bw.write("import " + modelPath + "." + modelName + ".entity.pdo." + className + "QueryReq;\n");
            bw.write("import com.bkgy.sys.common.entity.ResultData;\n");
            bw.write("import java.util.List;\n");
        }
        bw.write("import " + modelPath + "." + modelName + ".mapper.I" + className + "Mapper;\n");
        bw.write("import " + modelPath + "." + modelName + ".service.I" + className + "Service;\n");
        bw.write("import org.springframework.stereotype.Service;\n");
        bw.write("\n@Service\n");
        bw.write("public class " + className + "ServiceImpl extends ServiceImpl<I" + className + "Mapper," + className + "> implements I" + className + "Service {\n\n");

        if (withCRUD) {
            bw.write("\t@Override\n");
            bw.write("\tpublic ResultData<String> save" + className + "(" + className + " obj) {\n");
            bw.write("\t\tboolean res = false;\n");
            bw.write("\t\ttry {\n");
            bw.write("\t\t\tres = save(obj);\n");
            bw.write("\t\t} catch (Exception e) {\n");
            bw.write("\t\t\te.printStackTrace();\n");
            bw.write("\t\t\tlog.error(e.getMessage());\n");
            bw.write("\t\t}\n");
            bw.write("\t\treturn ResultData.ResultDataSuccess(res ? \"SUCCESS\" : \"FAIL\");\n");
            bw.write("\t}\n\n");

            bw.write("\t@Override\n");
            bw.write("\tpublic ResultData<String> update" + className + "(" + className + " obj) {\n");
            bw.write("\t\tLambdaQueryWrapper<" + className + "> wrapper = new LambdaQueryWrapper<>();\n");
            bw.write("\t\t//TODO 填写更新条件\n");
            bw.write("\t\tboolean res = update(obj, wrapper);\n");
            bw.write("\t\treturn ResultData.ResultDataSuccess(res ? \"SUCCESS\" : \"FAIL\");\n");
            bw.write("\t}\n\n");

            bw.write("\t@Override\n");
            bw.write("\tpublic ResultData<String> delete" + className + "(" + className + " obj) {\n");
            bw.write("\t\tLambdaQueryWrapper<" + className + "> wrapper = new LambdaQueryWrapper<>();\n");
            bw.write("\t\t//TODO 填写删除条件\n");
            bw.write("\t\tboolean res = remove(wrapper);\n");
            bw.write("\t\treturn ResultData.ResultDataSuccess(res ? \"SUCCESS\" : \"FAIL\");\n");
            bw.write("\t}\n\n");

            bw.write("\t@Override\n");
            bw.write("\tpublic ResultData selectPage(" + className + "QueryReq req) {\n");
            bw.write("\t\tPage<" + className + "> p = new Page<>(req.getPageIndex(), req.getPageSize());\n");
            bw.write("\t\tLambdaQueryWrapper<" + className + "> wrapper = new LambdaQueryWrapper<>();\n");
            bw.write("\t\t//TODO 填写查询条件\n");
            bw.write("\t\tIPage<" + className + "> data = page(p, wrapper);\n");
            bw.write("\t\tList<" + className + "> list = data.getRecords();\n");
            bw.write("\t\treturn ResultData.ResultDataSuccess(data.getRecords(), (int) data.getTotal());\n");
            bw.write("\t}\n\n");
        }
        bw.write("}\n");

        bw.close();
        System.out.println("服务层实现类创建完毕");
    }

    //创建服务层接口
    private static void createService(String path, String modelPath, String className) throws IOException {
        File entityPath = new File(pubPath + "/java/" + path + "/" + modelName + "/service", "I" + className + "Service.java");
        if (entityPath.exists()) {
            entityPath.delete();
        }
        FileOutputStream fos = new FileOutputStream(entityPath);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write("package " + modelPath + "." + modelName + ".service;\n\n");
        bw.write("import com.baomidou.mybatisplus.extension.service.IService;\n");
        if (withCRUD) {
            bw.write("import " + modelPath + "." + modelName + ".entity.pdo." + className + "QueryReq;\n");
            bw.write("import com.bkgy.sys.common.entity.ResultData;\n\n");
        }
        bw.write("import " + modelPath + "." + modelName + ".entity." + className + ";\n");
        bw.write("\npublic interface I" + className + "Service extends IService<" + className + "> {\n");
        if (withCRUD) {
            bw.write("\tResultData selectPage(" + className + "QueryReq request);\n\n");
            bw.write("\tResultData<String> save" + className + "(" + className + " obj);\n\n");
            bw.write("\tResultData<String> update" + className + "(" + className + " obj);\n\n");
            bw.write("\tResultData<String> delete" + className + "(" + className + " obj);\n\n");
        }
        bw.write("}\n");

        bw.close();
        System.out.println("服务层接口创建完毕");
    }

    //创建controller文件
    private static void createController(String path, String modelPath, String className) throws IOException {
        File controllerPath = new File(pubPath + "/java" + path + "/" + modelName + "/controller", className + "Controller.java");
        if (controllerPath.exists()) {
            controllerPath.delete();
        }
        FileOutputStream fos = new FileOutputStream(controllerPath);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write("package " + modelPath + "." + modelName + ".controller;\n\n");
        if (withCRUD) {
            bw.write("import " + modelPath + "." + modelName + ".entity.pdo." + className + "QueryReq;\n");
            bw.write("import " + modelPath + "." + modelName + ".service.I" + className + "Service;\n");
            bw.write("import " + modelPath + "." + modelName + ".entity." + className + ";\n");
            bw.write("import com.bkgy.sys.common.entity.ResultData;\n");
            bw.write("import io.swagger.v3.oas.annotations.Operation;\n");
            bw.write("import org.springframework.beans.factory.annotation.Autowired;\n");
            bw.write("import org.springframework.web.bind.annotation.PostMapping;\n");
            bw.write("import org.springframework.web.bind.annotation.RequestBody;\n");
            bw.write("import org.springframework.web.bind.annotation.ResponseBody;\n");
        }
        bw.write("import io.swagger.v3.oas.annotations.tags.Tag;\n");
        bw.write("import org.springframework.stereotype.Controller;\n");
        bw.write("import org.springframework.web.bind.annotation.RequestMapping;\n\n");

        if (StringUtils.isNotEmpty(description))
            bw.write("@Tag(name = \"" + description + "\")\n");
        bw.write("@Controller\n");
        bw.write("@RequestMapping(\"/" + modelName + "\")\n");
        bw.write("public class " + className + "Controller {\n\n");
        if (withCRUD) {
            bw.write("\t@Autowired\n");
            bw.write("\tprivate I" + className + "Service service;\n\n");

            bw.write("\t@ResponseBody\n");
            bw.write("\t@Operation(summary = \"新增\")\n");
            bw.write("\t@PostMapping(\"/" + modelName + "add\")\n");
            bw.write("\tpublic ResultData<String> save" + modelName + " (@RequestBody " + className + " obj){\n");
            bw.write("\t\treturn service.save" + className + "(obj);\n");
            bw.write("\t}\n");

            bw.write("\t@ResponseBody\n");
            bw.write("\t@Operation(summary = \"修改\")\n");
            bw.write("\t@PostMapping(\"/" + modelName + "update\")\n");
            bw.write("\tpublic ResultData<String> update" + modelName + " (@RequestBody " + className + " obj){\n");
            bw.write("\t\treturn service.update" + className + "(obj);\n");
            bw.write("\t}\n");

            bw.write("\t@ResponseBody\n");
            bw.write("\t@Operation(summary = \"删除\")\n");
            bw.write("\t@PostMapping(\"/" + modelName + "delete\")\n");
            bw.write("\tpublic ResultData<String> delete" + modelName + " (@RequestBody " + className + " obj){\n");
            bw.write("\t\treturn service.delete" + className + "(obj);\n");
            bw.write("\t}\n");

            bw.write("\t@ResponseBody\n");
            bw.write("\t@Operation(summary = \"分页查询\")\n");
            bw.write("\t@PostMapping(\"/" + modelName + "Page\")\n");
            bw.write("\tpublic ResultData<String> selectPage (@RequestBody " + className + "QueryReq obj){\n");
            bw.write("\t\treturn service.selectPage(obj);\n");
            bw.write("\t}\n");
        }
        bw.write("}\n");

        bw.close();
        System.out.println("控制层文件创建完毕");
    }

    //生成持久层文件
    private static void createMapper(String path, String modelPath, String className) throws IOException {
        File mapperPath = new File(pubPath + "/java/" + path + "/" + modelName + "/mapper", "I" + className + "Mapper.java");
        if (mapperPath.exists()) {
            mapperPath.delete();
        }
        FileOutputStream fos = new FileOutputStream(mapperPath);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write("package " + modelPath + "." + modelName + ".mapper;\n\n");
        bw.write("import com.baomidou.mybatisplus.core.mapper.BaseMapper;\n");
        bw.write("import " + modelPath + "." + modelName + ".entity." + className + ";\n");
        bw.write("import org.apache.ibatis.annotations.Mapper;\n\n");
        bw.write("@Mapper\n");
        bw.write("public interface I" + className + "Mapper extends BaseMapper<" + className + "> {\n");
        bw.write("}\n");

        bw.close();
        System.out.println("持久层文件创建完毕");
    }

    //生成类文件
    private static void createEntity(String path, String modelPath, String className, Set<String> importList, List<String> fieldList) throws IOException {
        File entityPath = new File(pubPath + "/java/" + path + "/" + modelName + "/entity", className + ".java");
        if (entityPath.exists()) {
            entityPath.delete();
        }
        FileOutputStream fos = new FileOutputStream(entityPath);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write("package " + modelPath + "." + modelName + ".entity;\n\n");
        for (String imp : importList) {
            bw.write(imp + "\n");
        }

        bw.write("import lombok.Data;\n\n");
        bw.write("@Data\n");
        bw.write("public class " + className + " {\n");
        for (String field : fieldList) {
            bw.write("\t" + field + "\n");
        }
        bw.write("}");
        bw.close();

        if (withCRUD) {
            File pdoPath = new File(pubPath + "/java/" + path + "/" + modelName + "/entity/pdo", className + "QueryReq.java");
            if (pdoPath.exists()) {
                pdoPath.delete();
            }
            FileOutputStream fos2 = new FileOutputStream(pdoPath);
            OutputStreamWriter osw2 = new OutputStreamWriter(fos2);
            BufferedWriter bw2 = new BufferedWriter(osw2);
            bw2.write("package " + modelPath + "." + modelName + ".entity.pdo;\n\n");
            bw2.write("import com.bkgy.commom.model.PageParams;\n");
            bw2.write("import lombok.Data;\n\n");
            bw2.write("@Data\n");
            bw2.write("public class " + className + "QueryReq extends PageParams {\n\n");
            bw2.write("}\n");
            bw2.close();
        }

        System.out.println("实体文件创建完毕");
    }
}
